/*
 *  Copyright 2019-2020
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.qp.basics.admin.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.qp.basics.admin.repository.DictDetailRepository;
import com.qp.basics.admin.repository.DictRepository;
import com.qp.basics.admin.service.DictService;
import com.qp.basics.admin.service.dto.DictQueryCriteria;
import com.qp.basics.common.domain.Dict;
import com.qp.basics.common.domain.DictDetail;
import com.qp.basics.common.poi.ExcelX;
import com.qp.basics.common.service.dto.DictDetailDto;
import com.qp.basics.common.service.dto.DictDto;
import com.qp.basics.common.service.mapstruct.DictMapper;
import com.qp.basics.common.utils.*;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

/**
* @author
* @date 2019-04-10
*/
@Service
@RequiredArgsConstructor
@CacheConfig(cacheNames = "dict")
public class DictServiceImpl implements DictService {

    private final DictRepository dictRepository;
    private final DictMapper dictMapper;
    private final RedisUtils redisUtils;

    private final DictDetailRepository dictDetailRepository;

    @Override
    public Map<String, Object> queryAll(DictQueryCriteria dict, Pageable pageable){
        Page<Dict> page = dictRepository.findAll((root, query, cb) -> QueryHelp.getPredicate(root, dict, cb), pageable);
        return PageUtil.toPage(page.map(dictMapper::toDto));
    }

    @Override
    public List<DictDto> queryAll(DictQueryCriteria dict) {
        List<Dict> list = dictRepository.findAll((root, query, cb) -> QueryHelp.getPredicate(root, dict, cb));
        return dictMapper.toDto(list);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(Dict resources) {
        dictRepository.save(resources);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(Dict resources) {
        // 清理缓存
        delCaches(resources);
        Dict dict = dictRepository.findById(resources.getId()).orElseGet(Dict::new);
        ValidationUtil.isNull( dict.getId(),"Dict","id",resources.getId());
        resources.setId(dict.getId());
        dictRepository.save(resources);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Set<Long> ids) {
        // 清理缓存
        List<Dict> dicts = dictRepository.findByIdIn(ids);
        for (Dict dict : dicts) {
            delCaches(dict);
        }
        dictRepository.deleteByIdIn(ids);
    }

    @Override
    public void download(List<DictDto> dictDtos, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (DictDto dictDTO : dictDtos) {
            if(CollectionUtil.isNotEmpty(dictDTO.getDictDetails())){
                for (DictDetailDto dictDetail : dictDTO.getDictDetails()) {
                    Map<String,Object> map = new LinkedHashMap<>();
                    map.put("字典名称", dictDTO.getName());
                    map.put("字典类型", dictDTO.getType());
                    map.put("属性名称", dictDTO.getAttributeName());
                    map.put("字典描述", dictDTO.getDescription());
                    map.put("字典标签", dictDetail.getLabel());
                    map.put("字典值", dictDetail.getValue());
                    map.put("扩展值1", dictDetail.getValue2());
                    map.put("扩展值2", dictDetail.getValue3());
                    map.put("扩展值3", dictDetail.getValue4());
                    map.put("扩展值4", dictDetail.getValue5());
                    map.put("创建日期", dictDetail.getCreateTime());
                    list.add(map);
                }
            } else {
                Map<String,Object> map = new LinkedHashMap<>();
                map.put("字典名称", dictDTO.getName());
                map.put("字典类型", dictDTO.getType());
                map.put("属性名称", dictDTO.getAttributeName());
                map.put("字典描述", dictDTO.getDescription());
                map.put("字典标签", null);
                map.put("字典值", null);
                map.put("创建日期", dictDTO.getCreateTime());
                list.add(map);
            }
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    public JSONObject importExcel(MultipartFile file) {
        JSONObject res=new JSONObject();
        try (InputStream is = file.getInputStream()) {
            ExcelX ex = new ExcelX(is);
            List<Map> l = ex.excelToMapList(0);
            int count=0;
            int error=0;
            String  errorMsg = "";
            Map<String,Dict> dictMap = new HashMap<String,Dict>();
            for (int i = 0; i < l.size(); i++) {
                Map m = l.get(i);
                String name = ImortExportUtil.toStr(m.get("字典名称"));
                String type = ImortExportUtil.toStr(m.get("字典类型"));
                type = StringUtils.isNotEmpty(type)?type:"";
                String attributeName = ImortExportUtil.toStr(m.get("属性名称"));
                attributeName = StringUtils.isNotEmpty(attributeName)?attributeName:"";
                String description = ImortExportUtil.toStr(m.get("字典描述"));
                description = StringUtils.isNotEmpty(description)?description:"";
                String label = ImortExportUtil.toStr(m.get("字典标签"));
                label = StringUtils.isNotEmpty(label)?label:"";
                String value = ImortExportUtil.toStr(m.get("字典值"));
                value = StringUtils.isNotEmpty(value)?value:"";
                String value2 = ImortExportUtil.toStr(m.get("扩展值1"));
                value2 = StringUtils.isNotEmpty(value2)?value2:"";
                String value3 = ImortExportUtil.toStr(m.get("扩展值2"));
                value3 = StringUtils.isNotEmpty(value3)?value3:"";
                String value4 = ImortExportUtil.toStr(m.get("扩展值3"));
                value4 = StringUtils.isNotEmpty(value4)?value4:"";
                String value5 = ImortExportUtil.toStr(m.get("扩展值4"));
                value5 = StringUtils.isNotEmpty(value5)?value5:"";

                if (StringUtils.isEmpty(name)) {
                    errorMsg += "第"+(i+1)+"行记录导入失败找不到字典名称\n";
                    error++;
                    continue;
                }
                Dict dict = dictMap.get(name);
                if(dict==null){
                    Dict exDict = new Dict();
                    exDict.setName(name);
                    dict = dictRepository.findOne(Example.of(exDict)).get();
                    if(dict==null){
                        dict= new Dict();
                        dict.setName(name);
                    }
                    dict.setType(type);
                    dict.setAttributeName(attributeName);
                    dict.setDescription(description);
                    dict = dictRepository.save(dict);
                    dictMap.put(name,dict);
                }
                if (StringUtils.isEmpty(label)) {
                    errorMsg += "第"+(i+1)+"行记录导入失败找不到字典标签\n";
                    error++;
                    continue;
                }
                DictDetail exDictDetail = new DictDetail();
                exDictDetail.setLabel(label);
                exDictDetail.setDict(dict);
                ExampleMatcher matcher = ExampleMatcher.matching().withIgnorePaths("dictSort");
                Optional<DictDetail> optionalx = dictDetailRepository.findOne(Example.of(exDictDetail,matcher));
                DictDetail qDictDetail = null;
                if(Optional.empty().equals(optionalx)){
                    qDictDetail = new DictDetail();
                    qDictDetail.setLabel(label);
                }else{
                    qDictDetail = optionalx.get();
                }
                qDictDetail.setDict(dict);
                qDictDetail.setValue(value);
                qDictDetail.setValue2(value2);
                qDictDetail.setValue3(value3);
                qDictDetail.setValue4(value4);
                qDictDetail.setValue5(value5);
                dictDetailRepository.save(qDictDetail);
                count++;
            }
            res.put("msg","导入完成：共导入"+count+"条"+",失败"+error+"条\n"+errorMsg);
        }catch (IOException e) {
            e.printStackTrace();
            res.put("msg","导入失败："+e.getMessage());
        }
        return res;
    }


    public void delCaches(Dict dict){
        redisUtils.del("dict::name:" + dict.getName());
    }
}
